package com.tarena.lbs.business.servcie.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.github.pagehelper.PageHelper;

import com.github.pagehelper.PageInfo;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.attach.pojo.param.PicUpdateParam;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;

import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.business.api.BusinessApi;
import com.tarena.lbs.business.api.pojo.BusinessDto;
import com.tarena.lbs.business.dao.repository.BusinessRepository;
import com.tarena.lbs.business.dao.repository.StoreRepository;
import com.tarena.lbs.business.pojo.param.StoreParam;
import com.tarena.lbs.business.pojo.po.BusinessPO;
import com.tarena.lbs.business.pojo.param.UserLocationParam;

import com.tarena.lbs.business.pojo.po.StorePO;
import com.tarena.lbs.business.pojo.query.StoreQuery;

import com.tarena.lbs.business.pojo.vo.StoreVO;
import com.tarena.lbs.business.producer.AmqpDelayProducer;
import com.tarena.lbs.business.rpc.BusinessApiImpl;
import com.tarena.lbs.business.servcie.BusinessService;
import com.tarena.lbs.business.servcie.StoreService;
import com.tarena.lbs.common.enums.Roles;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.user.api.UserApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StoreServiceImpl implements StoreService {
    @Autowired
    public StoreRepository storeRepository;
    @DubboReference
    private BusinessApi businessApi;
    @DubboReference
    private AttachApi attachApi;
    @DubboReference
    private UserApi userApi;
    @Override
    public PageResult<StoreVO> pageStoreList(StoreQuery query) {
        // 创建一个新的分页结果对象，用于存储最终的分页查询结果
        PageResult<StoreVO> voPage = new PageResult<>();

        // 调用 storeRepository 的 pageStoreList 方法进行分页查询，获取包含店铺持久化对象的分页信息
        PageInfo<StorePO> pageInfo = storeRepository.pageStoreList(query);

        // 将分页信息中的页码设置到分页结果对象中
        voPage.setPageNo(pageInfo.getPageNum());
        // 将分页信息中的每页数量设置到分页结果对象中
        voPage.setPageSize(pageInfo.getPageSize());
        // 将分页信息中的总记录数设置到分页结果对象中
        voPage.setTotal(pageInfo.getTotal());
        // 声明一个存储店铺视图对象的列表
        List<StoreVO> vos = null;
        // 从分页信息中获取店铺持久化对象列表
        List<StorePO> pos = pageInfo.getList();
        // 判断持久化对象列表是否不为空
        if (CollectionUtils.isNotEmpty(pos)){
            vos = pos.stream().map(po -> {
                StoreVO vo = new StoreVO();
                BeanUtils.copyProperties(po, vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        return voPage;
    }

    @Override
    public List<StoreVO> location(UserLocationParam param) {
        // 1. 获取用户位置信息
        String longitude = param.getLongitude();
        String latitude = param.getLatitude();
        Integer userId = param.getUserId();

        // 2. 查询附近的店铺
        List<StoreVO> nearbyStores = storeRepository.getNearbyStores(longitude, latitude);

        // 3. 循环处理每个店铺
        for (StoreVO store : nearbyStores) {
            // 4. 封装消息
            Map<String, Object> message = new HashMap<>();
            message.put("userId", userId);
            message.put("storeId", store.getId());

            // 5. 发送消息到MQ
            sendMessageToMQ(message);
        }
        return nearbyStores;
    }

    private void sendMessageToMQ(Map<String, Object> message) {
        // 1. 定义延迟时间（例如：30秒）
        Integer delayTime = 30000; // 30秒

        // 2. 使用封装的生产者发送延迟消息
        AmqpDelayProducer<Map<String, Object>> producer = new AmqpDelayProducer<>();
        producer.sendDelay("store_location_exchange", "", message, delayTime);
    }

    @Override
    public PageResult<StoreVO> queryStoresByAreaAndBusiness(List<Long> cityIdList, Integer businessId, Integer pageNo, Integer pageSize) {
        // 创建分页结果对象
        PageResult<StoreVO> voPage = new PageResult<>();

        // 设置分页参数
        PageHelper.startPage(pageNo, pageSize);

        // 调用 repository 查询符合条件的店铺数据
        List<StorePO> storePOs = storeRepository.queryStoresByAreaAndBusiness(cityIdList, businessId);

        // 封装分页信息
        PageInfo<StorePO> pageInfo = new PageInfo<>(storePOs);
        voPage.setPageNo(pageInfo.getPageNum());
        voPage.setPageSize(pageInfo.getPageSize());
        voPage.setTotal(pageInfo.getTotal());

        // 转换 PO 到 VO
        List<StoreVO> storeVOs = null;
        if (CollectionUtils.isNotEmpty(storePOs)) {
            storeVOs = storePOs.stream().map(po -> {
                StoreVO vo = new StoreVO();
                BeanUtils.copyProperties(po, vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(storeVOs);

        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addStore(StoreParam param) {
        try {
            //1.检查当前登录用户的角色是否符合我当前业务的角色要求
            //SHOP 商家账号 能创建店铺
            checkRole(Roles.SHOP);
            // 检查商家是否存在（通过 businessId）
            Integer businessId = param.getBusinessId();
            BusinessPO businessPO = storeRepository.getBusinessById(businessId);
            Asserts.isTrue(businessPO == null,
                    new BusinessException("-4", "商家不存在，businessId = " + businessId));
            //验证检查幂等 是否存在相同名称的商家数据
            // 通过查询所有商家来检查名称是否重复
            List<StorePO> allStores = storeRepository.getStores();
            boolean nameExists = allStores.stream()
                    .anyMatch(store -> store.getStoreName().equals(param.getStoreName()));
            Asserts.isTrue(nameExists, new BusinessException("-1","商家名称已存在"));
            //3.幂等验证正常 可以新增 封装 数据对象PO 执行save新增
            Integer id = saveStore(param);
        }catch (BusinessException e){
            e.printStackTrace();
        }
    }

    private Integer saveStore(StoreParam param) {
        log.info("保存店铺数据：{}", param);
        StorePO storePO = new StorePO();
        BeanUtils.copyProperties(param, storePO);
        storePO.setStoreLongitude(param.getLongitude());
        storePO.setStoreLatitude(param.getLatitude());
        storePO.setCreateTime(new Date());
        storePO.setUpdateTime(new Date());
        storeRepository.insertStore(storePO);
        return storePO.getId();
    }

    private void checkRole(Roles requiredRole) throws BusinessException {
        // 1. 从ThreadLocal获取当前登录用户信息（确保是当前登录用户）
        UserPrinciple currentUser = AuthenticationContextUtils.get();
        // 2. 校验是否登录：未登录则阻断
        if (currentUser == null) {
            throw new BusinessException("-1","请先登录，仅登录用户可操作");
        }

        // 3. 获取当前用户的角色类型（与Roles枚举的type匹配）
        Integer userRoleType = currentUser.getRole().getType(); // 假设UserPrinciple有此方法
        if (userRoleType == null) {
            throw new BusinessException("-2","用户角色信息缺失，请联系管理员");
        }

        // 4. 严格校验是否为指定角色（此处即ADMIN，type=0）
        if (!requiredRole.getType().equals(userRoleType)) {
            // 解析当前用户的实际角色，返回清晰的异常信息
            throw new BusinessException("-3","当前用户角色不符合要求，请检查");
        }
    }
}
